using System;
using System.Collections.Generic;
using System.Linq;

namespace MinesweeperGame
{
    /// <summary>
    /// 游戏板类，管理扫雷游戏的核心逻辑
    /// </summary>
    public class GameBoard
    {
        /// <summary>
        /// 游戏板行数
        /// </summary>
        public int Rows { get; private set; }

        /// <summary>
        /// 游戏板列数
        /// </summary>
        public int Cols { get; private set; }

        /// <summary>
        /// 地雷数量
        /// </summary>
        public int MineCount { get; private set; }

        /// <summary>
        /// 游戏板方块数组
        /// </summary>
        public Cell[,] Cells { get; private set; }

        /// <summary>
        /// 剩余地雷数量
        /// </summary>
        public int RemainingMines { get; private set; }

        /// <summary>
        /// 已揭开的方块数量
        /// </summary>
        public int RevealedCells { get; private set; }

        /// <summary>
        /// 随机数生成器
        /// </summary>
        private Random random;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="rows">行数</param>
        /// <param name="cols">列数</param>
        /// <param name="mineCount">地雷数量</param>
        public GameBoard(int rows, int cols, int mineCount)
        {
            Rows = rows;
            Cols = cols;
            MineCount = mineCount;
            RemainingMines = mineCount;
            RevealedCells = 0;
            random = new Random();

            InitializeBoard();
        }

        /// <summary>
        /// 初始化游戏板
        /// </summary>
        private void InitializeBoard()
        {
            Cells = new Cell[Rows, Cols];
            for (int row = 0; row < Rows; row++)
            {
                for (int col = 0; col < Cols; col++)
                {
                    Cells[row, col] = new Cell(row, col);
                }
            }
        }

        /// <summary>
        /// 重置游戏板
        /// </summary>
        public void Reset()
        {
            RemainingMines = MineCount;
            RevealedCells = 0;
            for (int row = 0; row < Rows; row++)
            {
                for (int col = 0; col < Cols; col++)
                {
                    Cells[row, col].Reset();
                }
            }
        }

        /// <summary>
        /// 布置地雷（第一次点击后）
        /// </summary>
        /// <param name="firstRow">第一次点击的行</param>
        /// <param name="firstCol">第一次点击的列</param>
        public void PlaceMines(int firstRow, int firstCol)
        {
            int minesPlaced = 0;
            while (minesPlaced < MineCount)
            {
                int row = random.Next(Rows);
                int col = random.Next(Cols);

                // 确保不在第一次点击的位置及其周围放置地雷
                if (!Cells[row, col].IsMine && 
                    (Math.Abs(row - firstRow) > 1 || Math.Abs(col - firstCol) > 1))
                {
                    Cells[row, col].IsMine = true;
                    minesPlaced++;
                }
            }

            // 计算每个方块周围的地雷数量
            CalculateAdjacentMineCounts();
        }

        /// <summary>
        /// 计算每个方块周围的地雷数量
        /// </summary>
        private void CalculateAdjacentMineCounts()
        {
            for (int row = 0; row < Rows; row++)
            {
                for (int col = 0; col < Cols; col++)
                {
                    if (!Cells[row, col].IsMine)
                    {
                        Cells[row, col].AdjacentMineCount = CountAdjacentMines(row, col);
                    }
                }
            }
        }

        /// <summary>
        /// 计算指定位置周围的地雷数量
        /// </summary>
        /// <param name="row">行索引</param>
        /// <param name="col">列索引</param>
        /// <returns>周围地雷数量</returns>
        public int CountAdjacentMines(int row, int col)
        {
            int count = 0;
            var adjacentCells = GetAdjacentCells(row, col);
            
            foreach (var cell in adjacentCells)
            {
                if (cell.IsMine)
                {
                    count++;
                }
            }
            
            return count;
        }

        /// <summary>
        /// 获取指定位置周围的方块
        /// </summary>
        /// <param name="row">行索引</param>
        /// <param name="col">列索引</param>
        /// <returns>周围方块列表</returns>
        public List<Cell> GetAdjacentCells(int row, int col)
        {
            var adjacentCells = new List<Cell>();
            
            for (int r = Math.Max(0, row - 1); r <= Math.Min(Rows - 1, row + 1); r++)
            {
                for (int c = Math.Max(0, col - 1); c <= Math.Min(Cols - 1, col + 1); c++)
                {
                    if (r != row || c != col)
                    {
                        adjacentCells.Add(Cells[r, c]);
                    }
                }
            }
            
            return adjacentCells;
        }

        /// <summary>
        /// 揭开方块
        /// </summary>
        /// <param name="row">行索引</param>
        /// <param name="col">列索引</param>
        /// <returns>是否踩到地雷</returns>
        public bool RevealCell(int row, int col)
        {
            if (row < 0 || row >= Rows || col < 0 || col >= Cols)
                return false;

            var cell = Cells[row, col];
            
            if (cell.IsRevealed || cell.IsFlagged)
                return false;

            cell.Reveal();
            RevealedCells++;

            // 如果踩到地雷
            if (cell.IsMine)
            {
                return true;
            }

            // 如果是空白方块，自动展开周围的方块
            if (cell.AdjacentMineCount == 0)
            {
                var adjacentCells = GetAdjacentCells(row, col);
                foreach (var adjacentCell in adjacentCells)
                {
                    if (!adjacentCell.IsRevealed && !adjacentCell.IsFlagged)
                    {
                        RevealCell(adjacentCell.Row, adjacentCell.Col);
                    }
                }
            }

            return false;
        }

        /// <summary>
        /// 标记/取消标记方块
        /// </summary>
        /// <param name="row">行索引</param>
        /// <param name="col">列索引</param>
        public void ToggleFlag(int row, int col)
        {
            if (row < 0 || row >= Rows || col < 0 || col >= Cols)
                return;

            var cell = Cells[row, col];
            
            if (cell.IsRevealed)
                return;

            bool wasFlagged = cell.IsFlagged;
            cell.ToggleFlag();
            
            if (wasFlagged)
            {
                RemainingMines++;
            }
            else
            {
                RemainingMines--;
            }
        }

        /// <summary>
        /// 检查游戏是否获胜
        /// </summary>
        /// <returns>是否获胜</returns>
        public bool IsGameWon()
        {
            // 方法1：所有非地雷方块都被揭开
            if (RevealedCells == (Rows * Cols - MineCount))
            {
                return true;
            }
            
            // 方法2：所有地雷都被正确标记
            int correctlyFlaggedMines = 0;
            int totalFlags = 0;
            
            for (int row = 0; row < Rows; row++)
            {
                for (int col = 0; col < Cols; col++)
                {
                    var cell = Cells[row, col];
                    if (cell.IsFlagged)
                    {
                        totalFlags++;
                        if (cell.IsMine)
                        {
                            correctlyFlaggedMines++;
                        }
                    }
                }
            }
            
            // 如果所有地雷都被正确标记，且没有错误标记，则获胜
            return correctlyFlaggedMines == MineCount && totalFlags == MineCount;
        }

        /// <summary>
        /// 获取所有地雷位置
        /// </summary>
        /// <returns>地雷位置列表</returns>
        public List<Cell> GetAllMines()
        {
            var mines = new List<Cell>();
            for (int row = 0; row < Rows; row++)
            {
                for (int col = 0; col < Cols; col++)
                {
                    if (Cells[row, col].IsMine)
                    {
                        mines.Add(Cells[row, col]);
                    }
                }
            }
            return mines;
        }

        /// <summary>
        /// 获取所有未标记的地雷
        /// </summary>
        /// <returns>未标记的地雷列表</returns>
        public List<Cell> GetUnflaggedMines()
        {
            var mines = new List<Cell>();
            for (int row = 0; row < Rows; row++)
            {
                for (int col = 0; col < Cols; col++)
                {
                    if (Cells[row, col].IsMine && !Cells[row, col].IsFlagged)
                    {
                        mines.Add(Cells[row, col]);
                    }
                }
            }
            return mines;
        }

        /// <summary>
        /// 获取所有错误标记的方块
        /// </summary>
        /// <returns>错误标记的方块列表</returns>
        public List<Cell> GetWronglyFlaggedCells()
        {
            var wrongFlags = new List<Cell>();
            for (int row = 0; row < Rows; row++)
            {
                for (int col = 0; col < Cols; col++)
                {
                    if (Cells[row, col].IsFlagged && !Cells[row, col].IsMine)
                    {
                        wrongFlags.Add(Cells[row, col]);
                    }
                }
            }
            return wrongFlags;
        }
    }
} 